import os
import openpyxl

from tkinter import messagebox
from openpyxl import Workbook
from dataclasses import dataclass


@dataclass
class WorkBook:
    workbook: openpyxl.Workbook
    filename: str


def read_excel_files_from_folder(folder_path):
    """
    该函数从指定的文件夹路径读取所有 Excel 文件并返回 openpyxl 工作簿对象的列表。
    
    :param folder_path: 文件夹路径是存储Excel文件的文件夹位置。它应该是一个表示文件夹的绝对或相对路径的字符串。
    :return: openpyxl 工作簿对象的列表。
    """
    workbooks = []
    # 如果没有文件夹，就创建一个
    if not os.path.exists(folder_path):
        os.makedirs(folder_path)
        return workbooks
    
    for filename in os.listdir(folder_path):
        if filename.endswith('.xlsx') or filename.endswith('.xls'):
            workbook = openpyxl.load_workbook(os.path.join(folder_path, filename))
            workbooks.append(WorkBook(workbook, filename[:-5]))
    return workbooks


def read_specific_excel_files(file_paths):
    """
    该函数从给定的文件路径读取特定的 Excel 文件并返回已加载工作簿的列表。
    
    :param file_paths: 您要读取的特定 Excel 文件的文件路径列表。
    :return: openpyxl 工作簿对象的列表。
    """
    workbooks = []

    for file_path in file_paths:
        if os.path.exists(file_path):
            workbook = openpyxl.load_workbook(file_path)
            workbooks.append(workbook)
        else:
            workbooks.append(None)
            print(f"文件 {file_path} 不存在，已跳过。")
    return workbooks


def read_first_column(workbook):
    """
    该函数读取工作簿中所有工作表的第一列。

    :param workbook: openpyxl 工作簿对象。
    :return: 包含第一列所有值的列表。
    """
    first_column_values = []
    if workbook is None:
        return first_column_values, 0

    max_value_length = 0
    for sheet in workbook.worksheets:
        for row in sheet.iter_rows(min_row=1, max_col=1, values_only=True):
            # 更新最大值长度 
            if max_value_length < len(row[0]):
                max_value_length = len(row[0])

            first_column_values.append(row[0])
    return first_column_values, max_value_length


def get_element(list_, index):
    """
    该函数尝试从列表中获取指定索引的元素。如果索引超出范围，它将返回 None。

    :param list_: 要获取元素的列表。
    :param index: 要获取的元素的索引。
    :return: 指定索引的元素，如果索引超出范围，则为 None。
    """
    try:
        return list_[index]
    except IndexError:
        return None


def write_list_to_excel(list_, file_path):
    """
    该函数将列表的内容写入到 Excel 文件的一列中。

    :param list_: 要写入的列表。
    :param file_path: 要写入的 Excel 文件的路径。
    """
    workbook = Workbook()
    sheet = workbook.active

    for item in list_:
        sheet.append([item])

    workbook.save(file_path)


def process_values(values, rule, max_value_length):
    """
    函数“process_values”接受值列表、规则和最大值长度，并返回两个列表 - 一个包含与规则匹配的值，另一个包含与规则不匹配的值。
    
    :param values: 需要处理的值的列表。
    :param rule: “rule”参数是一个字符串列表，表示我们在“values”列表的每个值中查找的值集。
    :param max_value_length: “max_value_length”参数是将根据“rule”检查的子字符串的最大长度。
    :return: 两个列表：“new_list”和“remaining_values”。
    """

    new_list = []
    remaining_values = []
    for value in values:
        flag = False
        for step in range(max_value_length, 0, -1):
            for i in range(len(value) - step + 1):
                if value[i:i + step] in rule:
                    new_list.append(value)
                    flag = True
                    break
            if flag:
                break
        if not flag:
            remaining_values.append(value)
    return new_list, remaining_values


if __name__ == '__main__':
    # 初始化文件夹
    # read_excel_files_from_folder('input')
    # read_excel_files_from_folder('output')
    # read_excel_files_from_folder('rule')

    # 读取规则 Excel 文件
    rule_workbooks = read_specific_excel_files(['rule/tob.xlsx', 'rule/toc.xlsx'])
    tob_rule, tob_max_value_length = read_first_column(rule_workbooks[0])
    toc_rule, toc_max_value_length = read_first_column(rule_workbooks[1])
    print(tob_rule, tob_max_value_length)
    print(toc_rule, toc_max_value_length)

    input_workbooks = read_excel_files_from_folder('input')
    # 遍历输入的 Excel 文件
    for workbook in input_workbooks:
        tob_list = []
        toc_list = []

        values, _ = read_first_column(workbook.workbook)
        tob_list, values = process_values(values, tob_rule, tob_max_value_length)
        toc_list, values = process_values(values, toc_rule, toc_max_value_length)
  
        print(f"tob list => {tob_list}")
        print(f"toc list => {toc_list}")
        write_list_to_excel(tob_list, f'output/{workbook.filename}_tob.xlsx')
        write_list_to_excel(toc_list, f'output/{workbook.filename}_toc.xlsx')
        write_list_to_excel(values, f'output/{workbook.filename}_unknown.xlsx')

    messagebox.showinfo('提示', '处理完成！')
